use anyhow::{anyhow, Result};
use fudata::db::Record;
use fudata::model::Security;
use regex::Regex;
use reqwest::Client;
use utils::Market;

use crate::helper::{self};
pub struct FundCraw {
    pub fund: Security,
}

impl FundCraw {
    /// update fund basic information
    ///
    /// code: e.g. 516760
    pub async fn update_basic_from_eastmoney(
        client: 
        code: &str,
    ) -> Result<Option<Record>> {
        let jbgk = eastmoney::fund::fund_jbgk::FundJbgk::fund_jbgk( code)
            .await
            .map_err(|err| anyhow!(err.to_string()))?;
        let fund_craw: FundCraw = jbgk.into();
        let mut security: Security = fund_craw.fund;

        let market: Market =
            helper::get_stock_market(code).map_err(|err| anyhow!(err.to_string()))?;
        let id = format!("{}.{}", code, market);

        // ignore below four to update as already done by funds_craw::update_etf_list_from_eastmoney()
        // symbol: code.to_owned(),
        // name: Some(name.to_owned()),
        // market: Some(market),
        // type_: Some(SecurityType::ETF),
        security.symbol = None;
        security.name = None;
        security.market = None;
        security.type_ = None;

        println!("update_basic_from_eastmoney security={:?}", security);

        let updated = fudata::db::security::upsert(&id, security).await?;

        Ok(updated)
    }
}

impl From<eastmoney::fund::fund_jbgk::FundJbgk> for FundCraw {
    fn from(v: eastmoney::fund::fund_jbgk::FundJbgk) -> Self {
        // Define a regular expression pattern to match the date in the format "YYYY年MM月DD日".
        let date_pattern = Regex::new(r"(\d{4}年\d{2}月\d{2}日)").unwrap();
        // let number_pattern = Regex::new(r"(-?\d+\.\d+)").unwrap();
        //发行日期	2013年03月25日
        let mut issue_date = "";
        if let Some(caps) = date_pattern.captures(&v.issue_date) {
            // Extract the date string from the first capture group.
            issue_date = caps.get(1).map_or("", |m| m.as_str());
            println!("Extracted date: {}", issue_date);
        } else {
            println!("No date found in the input string.");
        }
        let clear_issue_date = dateparser::parse(issue_date).unwrap_or_default();

        // 成立日期/规模: "2013年03月29日 / 42.220亿份"
        // let mut found_date = "";
        // if let Some(caps) = date_pattern.captures(&v.establishment_date_size) {
        //     // Extract the date string from the first capture group.
        //     found_date = caps.get(1).map_or("", |m| m.as_str());
        //     println!("Extracted date: {}", found_date);
        // } else {
        //     println!("No date found in the input string.");
        // }

        // let clear_found_date = dateparser::parse(found_date).unwrap_or_default();
        // let mut clear_issue_amount = 0.0;
        // if let Some(caps) = number_pattern.captures(&v.establishment_date_size) {
        //     // Extract the number string from the first capture group.
        //     if let Some(number_str) = caps.get(1) {
        //         // Parse the extracted string as a f64.
        //         clear_issue_amount = number_str.as_str().parse().unwrap_or_default();
        //         println!("Extracted clear_issue_amount: {}", clear_issue_amount);
        //     } else {
        //         println!("No number found in the input string.");
        //     }
        // } else {
        //     println!("No number found in the input string.");
        // }
        //
        // let re_fee = Regex::new(r"[^0-9.]").unwrap();
        // // let result = re.replace_all(input, "");
        // let clear_management_fee_rate = re_fee.replace_all(&v.management_fee_rate, "");
        // let clear_custodian_fee_rate = re_fee.replace_all(&v.custodian_fee_rate, "");
        // let mut clear_asset_size = 0.0;
        //
        // // Create a regex pattern to match a number with an optional decimal point
        // let re = Regex::new(r"(\d+(?:\.\d+)?)").unwrap();
        // // Find the first match in the text：10.56亿元（截止至：2023年12月31日）
        // if let Some(capture) = re.captures(&v.asset_size) {
        //     // Extract the captured value
        //     if let Some(value) = capture.get(1) {
        //         println!("资产规模万元 Extracted value: {}", value.as_str());
        //         clear_asset_size = f64::from_str(value.as_str()).unwrap_or_default() * 10000f64;
        //     }
        // } else {
        //     println!("No match found for 资产规模万元.");
        // }

        Self {
            fund: Security {
                name: Some(v.short_name),
                type_: Some("ETF".to_string()),
                ipo_date: Some(clear_issue_date),

                ..Default::default()
            },
        }
    }
}

#[cfg(test)]
mod test {

    use super::*;

    use fudata::db::FUDB;
    use serde::Deserialize;
    use surrealdb::Response;

    #[derive(Debug, Deserialize, PartialEq)]
    struct Count {
        count: u64,
    }

    #[tokio::test]
    async fn test_update_basic_from_eastmoney() {
        let _ = fudata::db::init().await.unwrap();

        let codes = [
            "516760",
            // "159867", "513130", "159001"
        ];
        for code in codes {
            let r1 = FundCraw::update_basic_from_eastmoney( code).await;

            println!("\nresult1={:?}", r1);
            assert_eq!(r1.is_ok(), true);
            if let Ok(fund) = r1 {
                println!("\nfund= {:?}\n", fund);
            }
        }

        let mut response: Response = FUDB
            .query("select count() from fund where fd_code in ['516760','159867'] group all")
            .await
            .unwrap();

        println!("\n response={:?} ", response);
        let xx: Option<Count> = response.take(0).expect("count NOT FOUND");
        println!("\n response={:?} \n xx={:?}", response, xx);

        assert_eq!(Some(Count { count: 2 }), xx);
    }
}
